/* GTKMM Plugin */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "menus.hh"

#include <gtkmm/main.h>
#include <gtkmm/menu.h>
#include <gtkmm/image.h>
#include <gtkmm/imagemenuitem.h>
#include <gtkmm/separatormenuitem.h>

#include <vlc_intf_strings.h>

#include "main_interface.hh"
#include "pixmaps/resources.h"
#include "util/string.hh"

#include <vector>

VlcMenuBar::VlcMenuBar (MainInterface *mi, intf_thread_t *_p_i) : p_intf (_p_i), m_toplevel (mi)
{

  append (*create_media_menu ());
  append (*create_playlist_menu ());
  append (*create_tools_menu ());
  append (*create_audio_menu ());
  append (*create_video_menu ());
  append (*create_playback_menu ());
  append (*create_help_menu ());

}

VlcMenuBar::~VlcMenuBar ()
{}

// - - - - - - - - - - Media menu
Gtk::MenuItem*
VlcMenuBar::create_media_menu ()
{

  Gtk::MenuItem *item = new Gtk::MenuItem (q2gm (_("&Media")), true);
  Gtk::Menu *menu = new Gtk::Menu ();

  Gtk::ImageMenuItem *image_item = new Gtk::ImageMenuItem (\
    *Gtk::manage (new Gtk::Image (Gdk::Pixbuf::create_from_inline (-1, vlc_open_file))),
    q2gm (_("&Open File...")),
    true);
  image_item->signal_activate ().connect (sigc::mem_fun (this, &VlcMenuBar::open));
  image_item->add_accelerator ("activate", m_toplevel->get_accel_group (), GDK_O, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
  menu->append (*Gtk::manage (image_item));

  /* FIXME: Open D&irectory is i18n with the accelerator :s */
  image_item = new Gtk::ImageMenuItem (*Gtk::manage (\
    new Gtk::Image (Gdk::Pixbuf::create_from_inline (-1, vlc_open_dir))),
    q2gm (_("Open D&irectory...")),
    true);
  image_item->add_accelerator ("activate", m_toplevel->get_accel_group (), GDK_F, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
  menu->append (*Gtk::manage (image_item));

  image_item = new Gtk::ImageMenuItem (*Gtk::manage (\
    new Gtk::Image (Gdk::Pixbuf::create_from_inline (-1, vlc_open_disc))),
    q2gm (_("Open &Disc...")),
    true);
  image_item->add_accelerator ("activate", m_toplevel->get_accel_group (), GDK_D, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
  menu->append (*Gtk::manage (image_item));

  image_item = new Gtk::ImageMenuItem (*Gtk::manage (\
    new Gtk::Image (Gdk::Pixbuf::create_from_inline (-1, vlc_open_network))),
    q2gm (_("Open &Network...")),
    true);
  image_item->add_accelerator ("activate", m_toplevel->get_accel_group (), GDK_N, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
  menu->append (*Gtk::manage (image_item));

  image_item = new Gtk::ImageMenuItem (*Gtk::manage (\
    new Gtk::Image (Gdk::Pixbuf::create_from_inline (-1, vlc_capture_device))),
    q2gm (_("Open &Capture Device...")),
    true);
  image_item->add_accelerator ("activate", m_toplevel->get_accel_group (), GDK_C, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
  menu->append (*Gtk::manage (image_item));

  menu->append (*Gtk::manage (new Gtk::SeparatorMenuItem ()));

  image_item = new Gtk::ImageMenuItem (*Gtk::manage (\
    new Gtk::Image (Gdk::Pixbuf::create_from_inline (-1, vlc_stream))),
    q2gm (_("&Streaming...")),
    true);  image_item->add_accelerator ("activate", m_toplevel->get_accel_group (), GDK_S, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
  menu->append (*Gtk::manage (image_item));

  image_item = new Gtk::ImageMenuItem (*Gtk::manage (\
    new Gtk::Image (Gdk::Pixbuf::create_from_inline (-1, vlc_convert))),
    q2gm (_("Conve&rt / Save..")),
    true);
  image_item->add_accelerator ("activate", m_toplevel->get_accel_group (), GDK_R, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
  menu->append (*Gtk::manage (image_item));

  menu->append (*Gtk::manage (new Gtk::SeparatorMenuItem ()));

  image_item = new Gtk::ImageMenuItem (*Gtk::manage (\
    new Gtk::Image (Gdk::Pixbuf::create_from_inline (-1, vlc_quit))),
    q2gm (_("&Quit")),
    true);
  image_item->signal_activate ().connect (sigc::ptr_fun (&Gtk::Main::quit));
  image_item->add_accelerator ("activate", m_toplevel->get_accel_group (), GDK_Q, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
  
  menu->append (*Gtk::manage (image_item));

  item->set_submenu (*Gtk::manage (menu));
  return Gtk::manage (item);

}

// - - - - - - - - - - Playlist menu
Gtk::MenuItem* 
VlcMenuBar::create_playlist_menu ()
{

  Gtk::MenuItem *item = new Gtk::MenuItem (q2gm (_("&Playlist")), true);
  Gtk::Menu *menu = new Gtk::Menu ();

  menu->append (*Gtk::manage (create_sd_menu ()));

  Gtk::ImageMenuItem *image_item = new Gtk::ImageMenuItem (*Gtk::manage (\
    new Gtk::Image (Gdk::Pixbuf::create_from_inline (-1, vlc_playlist))),
    q2gm (_("Show Playlist")),
    true);
  image_item->add_accelerator ("activate", m_toplevel->get_accel_group (), GDK_L, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
  menu->append (*Gtk::manage (image_item));

  menu->append (*Gtk::manage (new Gtk::SeparatorMenuItem ()));

  Gtk::MenuItem *sub_item = new Gtk::MenuItem (_(I_PL_LOAD));
  sub_item->add_accelerator ("activate", m_toplevel->get_accel_group (), GDK_X, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
  menu->append (*Gtk::manage (sub_item));
  
  sub_item = new Gtk::MenuItem (_(I_PL_SAVE));
  sub_item->add_accelerator ("activate", m_toplevel->get_accel_group (), GDK_Y, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
  menu->append (*Gtk::manage (sub_item));

  menu->append (*Gtk::manage (new Gtk::SeparatorMenuItem ()));
  
  sub_item = new Gtk::MenuItem (_("Undock from interface"));
  sub_item->add_accelerator ("activate", m_toplevel->get_accel_group (), GDK_U, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
  menu->append (*Gtk::manage (sub_item));

  item->set_submenu (*Gtk::manage (menu));
  return Gtk::manage (item);

}

// - - - - - - - - - - Tools menu
Gtk::MenuItem*
VlcMenuBar::create_tools_menu ()
{

  Gtk::MenuItem *item = new Gtk::MenuItem (q2gm (_("&Tools")), true);
  Gtk::Menu *menu = new Gtk::Menu ();

  Gtk::ImageMenuItem *image_item = new Gtk::ImageMenuItem (*Gtk::manage (\
    new Gtk::Image (Gdk::Pixbuf::create_from_inline (-1, vlc_ext_settings))),
    q2gm (_(I_MENU_EXT)),
    true);
  image_item->add_accelerator ("activate", m_toplevel->get_accel_group (), GDK_E, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
  menu->append (*Gtk::manage (image_item));

  menu->append (*Gtk::manage (new Gtk::SeparatorMenuItem ()));

  // Interface Sub-menu
  if (1) // FIXME
  {
    menu->append (*Gtk::manage (create_interfaces_menu ()));
    menu->append (*Gtk::manage (new Gtk::SeparatorMenuItem ()));
  }

  Gtk::CheckMenuItem *check_item = new Gtk::CheckMenuItem (_("Minimal View..."), false);
  check_item->add_accelerator ("activate", m_toplevel->get_accel_group (), GDK_H, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
  menu->append (*Gtk::manage (check_item));

  check_item = new Gtk::CheckMenuItem (_("Toggle Fullscreen Interface"), false);
  check_item->add_accelerator ("activate", m_toplevel->get_accel_group (), GDK_F11, Gdk::LOCK_MASK, Gtk::ACCEL_VISIBLE);
  menu->append (*Gtk::manage (check_item));

  check_item = new Gtk::CheckMenuItem (_("Advanced controls"), false);
  menu->append (*Gtk::manage (check_item));

  menu->append (*Gtk::manage (new Gtk::SeparatorMenuItem ()));

  image_item = new Gtk::ImageMenuItem (*Gtk::manage (\
    new Gtk::Image (Gdk::Pixbuf::create_from_inline (-1, vlc_messages))),
    q2gm (_(I_MENU_MSG)),
    true);
  image_item->signal_activate ().connect (sigc::mem_fun (*this, &VlcMenuBar::messages));
  image_item->add_accelerator ("activate", m_toplevel->get_accel_group (), GDK_M, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
  menu->append (*Gtk::manage (image_item));

  image_item = new Gtk::ImageMenuItem (*Gtk::manage (\
    new Gtk::Image (Gdk::Pixbuf::create_from_inline (-1, vlc_media_info))),
    q2gm (_(I_MENU_INFO)),
    true);
  image_item->add_accelerator ("activate", m_toplevel->get_accel_group (), GDK_I, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
  menu->append (*Gtk::manage (image_item));

  image_item = new Gtk::ImageMenuItem (*Gtk::manage (\
    new Gtk::Image (Gdk::Pixbuf::create_from_inline (-1, vlc_media_info))),
    q2gm (_(I_MENU_CODECINFO)),
    true);
  image_item->add_accelerator ("activate", m_toplevel->get_accel_group (), GDK_J, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
  menu->append (*Gtk::manage (image_item));

  image_item = new Gtk::ImageMenuItem (*Gtk::manage (\
    new Gtk::Image (Gdk::Pixbuf::create_from_inline (-1, vlc_bookmark))),
    q2gm (_(I_MENU_BOOKMARK)),
    true);
  image_item->add_accelerator ("activate", m_toplevel->get_accel_group (), GDK_B, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
  menu->append (*Gtk::manage (image_item));

#ifdef ENABLE_VLM
  Gtk::MenuItem *sub_item = new Gtk::MenuItem (_(I_MENU_VLM));
  sub_item->add_accelerator ("activate", m_toplevel->get_accel_group (), GDK_V, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
  menu->append (*Gtk::manage (sub_item));
#endif

  menu->append (*Gtk::manage (new Gtk::SeparatorMenuItem ()));

  image_item = new Gtk::ImageMenuItem (*Gtk::manage (\
    new Gtk::Image (Gdk::Pixbuf::create_from_inline (-1, vlc_pref))),
    q2gm (_("Preferences...")),
    true);
  image_item->add_accelerator ("activate", m_toplevel->get_accel_group (), GDK_P, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
  menu->append (*Gtk::manage (image_item));

  item->set_submenu (*Gtk::manage (menu));
  return Gtk::manage (item);

}

// - - - - - - - - - - Audio menu
Gtk::MenuItem*
VlcMenuBar::create_audio_menu ()
{

  Gtk::MenuItem *item = new Gtk::MenuItem (q2gm (_("&Audio")), true);
  Gtk::Menu *menu = new Gtk::Menu ();

  /* FIXME: need to add content */
  Gtk::MenuItem *sub_item = new Gtk::MenuItem (_("not yet implemented"));
  menu->append (*Gtk::manage (sub_item));

  item->set_submenu (*Gtk::manage (menu));
  return Gtk::manage (item);

}

// - - - - - - - - - - Video menu
Gtk::MenuItem*
VlcMenuBar::create_video_menu ()
{

    vlc_object_t *p_object;
//    vector<int> objects;
//    vector<const char *> varnames;

  Gtk::MenuItem *item = new Gtk::MenuItem (q2gm (_("&Video")), true);
  Gtk::Menu *menu = new Gtk::Menu ();

  /* FIXME: need to add content */
  Gtk::MenuItem *sub_item = new Gtk::MenuItem (_("not yet implemented"));
  menu->append (*Gtk::manage (sub_item));

  item->set_submenu (*Gtk::manage (menu));
  return Gtk::manage (item);

}

// - - - - - - - - - - Playback menu
Gtk::MenuItem*
VlcMenuBar::create_playback_menu ()
{

  Gtk::MenuItem *item = new Gtk::MenuItem (q2gm (_("&Playback")), true);
  Gtk::Menu *menu = new Gtk::Menu ();

  Gtk::MenuItem *sub_item = new Gtk::MenuItem (_(I_MENU_GOTOTIME));
  menu->append (*Gtk::manage (sub_item));
  sub_item->signal_activate ().connect (sigc::mem_fun (*this, &VlcMenuBar::gototime));
  sub_item->add_accelerator ("activate", m_toplevel->get_accel_group (), GDK_T, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
  item->set_submenu (*Gtk::manage (menu));

  return Gtk::manage (item);

}

// - - - - - - - - - - Help menu
Gtk::MenuItem*
VlcMenuBar::create_help_menu ()
{

  Gtk::MenuItem *item = new Gtk::MenuItem (q2gm (_("&Help")), true);
  Gtk::Menu *menu = new Gtk::Menu ();

  Gtk::ImageMenuItem *image_item = new Gtk::ImageMenuItem (*Gtk::manage (\
    new Gtk::Image (Gdk::Pixbuf::create_from_inline (-1, vlc_help))),
    _("Help..."),
    true);
  image_item->signal_activate ().connect (sigc::mem_fun (*this, &VlcMenuBar::help));
  image_item->add_accelerator ("activate", m_toplevel->get_accel_group (), GDK_F1, Gdk::LOCK_MASK, Gtk::ACCEL_VISIBLE);
  menu->append (*Gtk::manage (image_item));

#ifdef UPDATE_CHECK
  Gtk::MenuItem *s_item = new Gtk::MenuItem (_("Update"), true);
  menu->append (*Gtk::manage (s_item));
#endif

  menu->append (*Gtk::manage (new Gtk::SeparatorMenuItem ()));

  image_item = new Gtk::ImageMenuItem (*Gtk::manage (\
    new Gtk::Image (Gdk::Pixbuf::create_from_inline (-1, vlc_about))),
    _(I_MENU_ABOUT),
    true);
  image_item->signal_activate ().connect (sigc::mem_fun (*this, &VlcMenuBar::about));
  image_item->add_accelerator ("activate", m_toplevel->get_accel_group (), GDK_F1, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
  menu->append (*Gtk::manage (image_item));

  item->set_submenu (*Gtk::manage (menu));
  return Gtk::manage (item);

}

/* FIXME : connect events */
// - - - - - - - - - - Service Discovery SubMenu
Gtk::MenuItem*
VlcMenuBar::create_sd_menu ()
{

  Gtk::MenuItem *item = new Gtk::MenuItem (_(I_PL_SD));
  Gtk::Menu *menu = new Gtk::Menu ();

  char **ppsz_longnames;
  char **ppsz_names = services_discovery_GetServicesNames (p_intf, &ppsz_longnames);
  char **ppsz_name = ppsz_names, **ppsz_longname = ppsz_longnames;
  
  for (; *ppsz_name; ppsz_name++, ppsz_longname++)
   {
    
    Gtk::CheckMenuItem *check_menu = new Gtk::CheckMenuItem (*ppsz_longname);
    menu->append (*Gtk::manage (check_menu));
    
    if (playlist_IsServicesDiscoveryLoaded (THEPL, *ppsz_name))
      check_menu->set_active (true);
      
    if (!strcmp (*ppsz_name, "podcast"))
     {
      Gtk::MenuItem *sub_item = new Gtk::MenuItem (_("Configure podcasts..."));
      menu->append (*Gtk::manage (sub_item));
     }
      
    free (*ppsz_name);
    free (*ppsz_longname);

   }
   
  free (ppsz_names);
  free (ppsz_longnames);

  item->set_submenu (*Gtk::manage (menu));
  return Gtk::manage (item);

}


// - - - - - - - - - - Interface Sub-Menu, to list extras interface and skins
Gtk::MenuItem*
VlcMenuBar::create_interfaces_menu ()
{

  Gtk::MenuItem *item = new Gtk::MenuItem (_("Interfaces"));
  Gtk::Menu *menu = new Gtk::Menu ();

  std::vector<int> objects;
  std::vector<const char *> varnames;

  varnames.push_back( "intf-add" );
  objects.push_back( p_intf->i_object_id );

  // ADD Populate call


  if( !p_intf->pf_show_dialog ) //FIXME
  {
    menu->append (*Gtk::manage (new Gtk::SeparatorMenuItem ()));
    Gtk::MenuItem *sub_item = new Gtk::MenuItem (_("Switch to skins"));
    sub_item->add_accelerator ("activate", m_toplevel->get_accel_group (), GDK_Z, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
    menu->append (*Gtk::manage (sub_item));
    // NO NEED TO CHECK FOR WX -> WxWidgets & QT sux ;D
  }

  item->set_submenu (*Gtk::manage (menu));
  return Gtk::manage (item);

}
// Builders for automenus
/*
Gtk::Menu*
VlcMenuBar::Populate( intf_thread_t *p_intf,
                      Gtk::Menu *current,
                      std::vector< const char *> & varnames,
                      std::vector<int> & objects,
                      bool append )
{
    Gtk::Menu *menu = current;
    if (!menu)
        menu = new Gtk::Menu ();
    else if (!append)
        menu->set_submenu (0); //FIXME

    currentGroup = NULL;

    vlc_object_t *p_object;
    vlc_bool_t b_section_empty = false;
    int i;

#define APPEND_EMPTY { Gtk::MenuItem *sub_item = new Gtk::MenuItem (_("Empty"));\
              sub_item->set_sensitive (false);\
              menu->append (*Gtk::manage (sub_item)); }

    for ( i = 0; i < ( int )objects.size() ; i++ )
    {
        if ( !varnames[i] || !*varnames[i] )
        {
            if ( b_section_empty )
                APPEND_EMPTY;
            menu->append (*Gtk::manage (new Gtk::SeparatorMenuItem ()));
            b_section_empty = true;
            continue;
        }

        if ( objects[i] == 0 )
        {
            /// \bug What is this ?
            // Append( menu, varnames[i], NULL );
            b_section_empty = false;
            continue;
        }

        p_object = ( vlc_object_t * )vlc_object_get( objects[i] );
        if( p_object == NULL ) continue;

        b_section_empty = false;
        //Ugly specific stuff
        if ( strstr ( varnames[i], "intf-add" ) )
            CreateItem ( menu, varnames[i], p_object, false );
        else
            CreateItem ( menu, varnames[i], p_object, true );
        vlc_object_release( p_object );
    }

    // Special case for empty menus
    if ( menu->actions().size() == 0 || b_section_empty )
        APPEND_EMPTY;

    return menu;
}




static bool IsMenuEmpty (const char *psz_var,
                          vlc_object_t *p_object,
                          bool b_root = true )
{
    vlc_value_t val, val_list;
    int i_type, i_result, i;

    // Check the type of the object variable
    i_type = var_Type( p_object, psz_var );

    // Check if we want to display the variable
    if( !( i_type & VLC_VAR_HASCHOICE ) ) return false;

    var_Change( p_object, psz_var, VLC_VAR_CHOICESCOUNT, &val, NULL );
    if( val.i_int == 0 ) return true;

    if( ( i_type & VLC_VAR_TYPE ) != VLC_VAR_VARIABLE )
    {
        if( val.i_int == 1 && b_root ) return true;
        else return false;
    }

    // Check children variables in case of VLC_VAR_VARIABLE
    if( var_Change( p_object, psz_var, VLC_VAR_GETLIST, &val_list, NULL ) < 0 )
    {
        return true;
    }

    for( i = 0, i_result = true; i < val_list.p_list->i_count; i++ )
    {
        if( !IsMenuEmpty( val_list.p_list->p_values[i].psz_string,
                    p_object, false ) )
        {
            i_result = false;
            break;
        }
    }

    // clean up everything
    var_Change( p_object, psz_var, VLC_VAR_FREELIST, &val_list, NULL );

    return i_result;
}

void VlcMenuBar::CreateItem (Gtk::Menu *menu,
                            const char *psz_var,
                            vlc_object_t *p_object,
                            bool b_submenu)
{
    vlc_value_t val, text;
    int i_type;

    // Check the type of the object variable
    i_type = var_Type ( p_object, psz_var );

    switch ( i_type & VLC_VAR_TYPE )
    {
        case VLC_VAR_VOID:
        case VLC_VAR_BOOL:
        case VLC_VAR_VARIABLE:
        case VLC_VAR_STRING:
        case VLC_VAR_INTEGER:
        case VLC_VAR_FLOAT:
            break;
        default:
            // Variable doesn't exist or isn't handled
            return;
    }

    // Make sure we want to display the variable
    if( IsMenuEmpty( psz_var, p_object ) )  return;

    // Get the descriptive name of the variable
    var_Change( p_object, psz_var, VLC_VAR_GETTEXT, &text, NULL );

#define TEXT_OR_VAR _( text.psz_string ? text.psz_string : psz_var )

    if( i_type & VLC_VAR_HASCHOICE )
    {
        // Append choices menu
        if( b_submenu )
        {

            Gtk::MenuItem *item = new Gtk::MenuItem (TEXT_OR_VAR);
            Gtk::Menu *submenu = new Gtk::Menu ();
            if( CreateChoicesMenu( submenu, psz_var, p_object, true ) == 0 )
                menu->append (*Gtk::manage (submenu));
        }
        else
            CreateChoicesMenu( menu, psz_var, p_object, true );____________
        FREENULL( text.psz_string );
        return;
    }

    switch( i_type & VLC_VAR_TYPE )
    {
        case VLC_VAR_VOID:
            var_Get( p_object, psz_var, &val );
            CreateAndConnect( menu, psz_var, TEXT_OR_VAR, "", ITEM_NORMAL,
                    p_object->i_object_id, val, i_type );
            break;

        case VLC_VAR_BOOL:
            var_Get( p_object, psz_var, &val );
            val.b_bool = !val.b_bool;
            CreateAndConnect( menu, psz_var, TEXT_OR_VAR, "", ITEM_CHECK,
                    p_object->i_object_id, val, i_type, !val.b_bool );
            break;
    }
    FREENULL( text.psz_string );
}

int VlcMenuBar::CreateChoicesMenu( Gtk::Menu *submenu, const char *psz_var,
        vlc_object_t *p_object, bool b_root )
{
    vlc_value_t val, val_list, text_list;
    int i_type, i;

    // Check the type of the object variable
    i_type = var_Type( p_object, psz_var );

    // Make sure we want to display the variable
    if( IsMenuEmpty( psz_var, p_object, b_root ) ) return VLC_EGENERIC;

    switch( i_type & VLC_VAR_TYPE )
    {
        case VLC_VAR_VOID:
        case VLC_VAR_BOOL:
        case VLC_VAR_VARIABLE:
        case VLC_VAR_STRING:
        case VLC_VAR_INTEGER:
        case VLC_VAR_FLOAT:
            break;
        default:
            // Variable doesn't exist or isn't handled
            return VLC_EGENERIC;
    }

    if( var_Change( p_object, psz_var, VLC_VAR_GETLIST,
                &val_list, &text_list ) < 0 )
    {
        return VLC_EGENERIC;
    }

#define NORMAL_OR_RADIO i_type & VLC_VAR_ISCOMMAND ? ITEM_NORMAL: ITEM_RADIO
#define NOTCOMMAND !( i_type & VLC_VAR_ISCOMMAND )
#define CURVAL val_list.p_list->p_values[i]
#define CURTEXT text_list.p_list->p_values[i].psz_string

    for( i = 0; i < val_list.p_list->i_count; i++ )
    {
        vlc_value_t another_val;
        Gtk::Label *menutext;
        Gtk::Menu *subbubmenu = new Gtk::Menu ();

        switch( i_type & VLC_VAR_TYPE )
        {
            case VLC_VAR_VARIABLE:
                CreateChoicesMenu( subsubmenu, CURVAL.psz_string, p_object, false );
                subsubmenu->setTitle( gtr( CURTEXT ? CURTEXT :CURVAL.psz_string ) );
                submenu->addMenu( subsubmenu );
                break;

            case VLC_VAR_STRING:
                var_Get( p_object, psz_var, &val );
                another_val.psz_string = strdup( CURVAL.psz_string );
                menutext = gtr( "Add " ) // If this function is more used, FIXME
                         + gtr( CURTEXT ? CURTEXT : another_val.psz_string );
                CreateAndConnect( submenu, psz_var, menutext, "", NORMAL_OR_RADIO,
                        p_object->i_object_id, another_val, i_type,
                        NOTCOMMAND && val.psz_string &&
                        !strcmp( val.psz_string, CURVAL.psz_string ) );

                free( val.psz_string );
                break;

            case VLC_VAR_INTEGER:
                var_Get( p_object, psz_var, &val );
                if( CURTEXT ) menutext = gtr( CURTEXT );
                else menutext.sprintf( "%d", CURVAL.i_int );
                CreateAndConnect( submenu, psz_var, menutext, "", NORMAL_OR_RADIO,
                        p_object->i_object_id, CURVAL, i_type,
                        NOTCOMMAND && CURVAL.i_int == val.i_int );
                break;

            case VLC_VAR_FLOAT:
                var_Get( p_object, psz_var, &val );
                if( CURTEXT ) menutext = gtr( CURTEXT );
                else menutext.sprintf( "%.2f", CURVAL.f_float );
                CreateAndConnect( submenu, psz_var, menutext, "", NORMAL_OR_RADIO,
                        p_object->i_object_id, CURVAL, i_type,
                        NOTCOMMAND && CURVAL.f_float == val.f_float );
                break;

            default:
                break;
        }
    }
    currentGroup = NULL;

    // clean up everything
    var_Change( p_object, psz_var, VLC_VAR_FREELIST, &val_list, &text_list );

#undef NORMAL_OR_RADIO
#undef NOTCOMMAND
#undef CURVAL
#undef CURTEXT
    return VLC_SUCCESS;
}

void VlcMenuBar::CreateAndConnect( QMenu *menu, const char *psz_var,
        QString text, QString help,
        int i_item_type, int i_object_id,
        vlc_value_t val, int i_val_type,
        bool checked )
{
    QAction *action = new QAction( text, menu );
    action->setText( text );
    action->setToolTip( help );

    if( i_item_type == ITEM_CHECK )
    {
        action->setCheckable( true );
    }
    else if( i_item_type == ITEM_RADIO )
    {
        action->setCheckable( true );
        if( !currentGroup )
            currentGroup = new QActionGroup( menu );
        currentGroup->addAction( action );
    }

    if( checked )
    {
        action->setChecked( true );
    }
    MenuItemData *itemData = new MenuItemData( i_object_id, i_val_type,
            val, psz_var );
    CONNECT( action, triggered(), THEDP->menusMapper, map() );
    THEDP->menusMapper->setMapping( action, itemData );
    menu->addAction( action );
}

void VlcMenuBar::DoAction( intf_thread_t *p_intf, QObject *data )
{
    MenuItemData *itemData = qobject_cast<MenuItemData *>( data );
    vlc_object_t *p_object = ( vlc_object_t * )vlc_object_get( itemData->i_object_id );
    if( p_object == NULL ) return;

    var_Set( p_object, itemData->psz_var, itemData->val );
    vlc_object_release( p_object );
}
*/
